home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Tool Chest / Networking / Network Watch (DMZ) v1.3 / dMZMain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-16  |  39.2 KB  |  1,644 lines  |  [TEXT/MPS ]

  1. /*
  2. #-------------------------------------------------------------------------------------------
  3. #
  4. #    Program:    < DMZ 1.3 >
  5. #    File:        < dmzMain.c >
  6. #    
  7. #    by Pete Helme
  8. #    of <Apple Macintosh Developer Technical Support - or wheverever>
  9. #
  10. #    Modification History
  11. #    5/27/94     rrk    Implemented support for PPC
  12. #   2/1/94 by Peter Lovell, GE Information Services
  13. #    for Think C 6.0
  14. #    9/21/92  rrk    Implemented ATalk Trans Queue Handler
  15. #
  16. #    Copyright © 1990 Apple Computer, Inc.
  17. #    All rights reserved.
  18. #    
  19. #-------------------------------------------------------------------------------------------
  20. */
  21.  
  22. #include    "dmz.h"
  23.  
  24. #ifndef        _Gestalt
  25. #define        _Gestalt    0xA1AD
  26. #endif
  27.  
  28. #ifndef THINK_C
  29. extern _DataInit();
  30. #endif
  31.  
  32.  
  33. /*
  34.  *    imported Global Data objects, very expensive.
  35.  */
  36. extern char             gNameGlob[34];
  37. extern Boolean             gLookupFinished;
  38. extern Boolean             gUpdateListFlag;
  39. extern ListHandle         gZonesList, gObjectTypeList;
  40. extern PacketBuffer        gBuffers[kNumBuffers];
  41.  
  42.  
  43. /*
  44.  *    Global Data objects, used by routines external to main().
  45.  */
  46.  
  47.  
  48. /* 
  49.  *    gDoneFlag, becomes true when File/Quit chosen.
  50.  */
  51. Boolean        gDoneFlag;            
  52.  
  53. /* 
  54.  *    gMyDialog, our main dialog.
  55.  */
  56. DialogPtr    gMyDialog;                /* main dialog */
  57.  
  58. /* 
  59.  *    gLookupDialog, where we can set our preference for lookup times and lookup strings for
  60.  *    matching.
  61.  */
  62. DialogPtr    gLookupDialog;            /* dialog for NBP lookup prefs */
  63.  
  64. /* 
  65.  *    gSortMode is our global sort value.
  66.  */
  67. long    gSortMode;
  68.  
  69. /* 
  70.  *    gSortItem is our global sort value for which dialog item should be selected.
  71.  */
  72. short    gSortItem = kObjectID;    /* default is the object sleector */
  73.  
  74. /* 
  75.  *    gMyEvent is used for external access (from the event loop) to the event record.
  76.  *    The main outside client of this guy is use in the list routines.
  77.  */
  78. EventRecord        gMyEvent;
  79.  
  80. /* 
  81.  *    GMAC is used to hold the result of a SysEnvirons call. This makes
  82.  *    it convenient for any routine to check the environment. (What?!? no use of _Gestalt!?!? "Shuddup.")
  83.  */
  84. SysEnvRec    GMAC;                /* set up by Initialize */
  85.  
  86. /* 
  87.  *     gATalkFlags is used to track whether AppleTalk variables have been allocated, whether
  88.  *  VM is enabled, whether the transition queue handler has been installed, so that on 
  89.  *  cleanup, the appropriate actions can be taken.
  90.  */
  91. short    gATalkFlags = 0;        /* initialized right here */
  92.  
  93. /* 
  94.  *     gATQEntry is used to install an AppleTalk Transition Queue Handler so that
  95.  *     the program can handle changes to AppleTalk status.
  96.  */
  97.  
  98. myATQEntry    gATQEntry;            /* set up by Initialize */
  99.  
  100. /* 
  101.  *    gContLookUp is used as a flag to keep track of the state of whether or not we are doing
  102.  *    continuous network lookups.
  103.  */
  104. Boolean    gContLookUp = true;
  105.  
  106. /* 
  107.  *    GHasWaitNextEvent is set at startup, and tells whether the WaitNextEvent
  108.  *    trap is available. If it is false, we know that we must call GetNextEvent. 
  109.  */
  110. Boolean        gHasWaitNextEvent;    /* set up by Initialize */
  111.  
  112. /* 
  113.  *     GInBackground is maintained by our osEvent handling routines. Any part of
  114.  *     the program can check it to find out if it is currently in the background. 
  115.  */
  116. Boolean        gInBackground;        /* maintained by Initialize and DoEvent */
  117.  
  118. /* 
  119.  *     gAtalkTransUPP saves the universal procptr to the transition routine.  We only
  120.  *  want to allocate it once in the init routine, then reuse it as AppleTalk gets
  121.  *  turned on.  The use of the global var only makes sense is the application is to
  122.  *  be AppleTalk safe.  That is the user can turn AppleTalk on and off, and DMZ
  123.  *    does the right thing to protect itself
  124.  */
  125. ATalkTransitionEventUPP gAtalkTransUPP;        /* appletalk transition queue handler */
  126.  
  127. /* powerpc stuff */
  128.  
  129. #ifdef powerc
  130. QDGlobals qd;                                /* quickdraw globals */
  131. #endif
  132.  
  133.  
  134. /*
  135.  *    The Routines for dmzMain.
  136.  */
  137.  
  138.  
  139. #ifdef THINK_C2
  140. extern unsigned char * CrsrBusy : 0x8CD;
  141.  
  142. Ptr    gtheVBLPtr;
  143. Ptr    gtheTaskPtr;
  144.  
  145. void myVBLSpinInstall()
  146.     {
  147.     long        taskSize;
  148.     THz            curZone;
  149.     Handle        curses[4];
  150.     Ptr            taskAddress;
  151.         
  152.     /* load in the resources */
  153.     curses[1] = GetResource('CURS', 1001);
  154.     curses[2] = GetResource('CURS', 1002);
  155.     curses[3] = GetResource('CURS', 1003);
  156.     curses[4] = GetResource('CURS', 1004);
  157.         
  158.     asm {
  159.         bra     @theTaskEnd
  160.  
  161.     ; actual VBL Task
  162.     @theTaskBegin
  163.         movem.l    a0-a6/d0-d7, -(sp)        ; save 
  164.         bra.s    @1
  165.     @A5Storage
  166.         dc.l    0
  167.     @1
  168.         ; reset the vbl count
  169.         move.w     #5, OFFSET(VBLTask, vblCount)(a0)    
  170.         
  171.         ; restore A5 for globals we may have
  172.         lea        @A5Storage, a0
  173.         move.l    (a0), a5
  174.         bra.s    @45
  175.     @44    dc.w    #1001                ; storage for cursor type
  176.     @45    lea        @44, a0
  177.         add.w    #1, (a0)
  178.         move.w    (a0), d0
  179.         cmp.w    #1005, d0
  180.         blt        @10
  181.         
  182.         move.w    #1001, (a0)            ; start over with cursor type #1001
  183.         move.w    #1001, d0            ; it needs to be in d0
  184.         
  185.     @10    clr.l    -(a7)                ; make some space for return
  186.         move.w    d0, -(a7)            ; move in cursor type
  187.         _GetCursor
  188.         move.l    (a7)+, a0            ; move handle into a0
  189.         tst.b    CrsrBusy
  190.         bne.s    @vblExit
  191.         move.l    (a0), -(a7)            ; deref and push on stack
  192.         _SetCursor            
  193.     @vblExit
  194.         movem.l     (sp)+, a0-a6/d0-d7    ; restore 
  195.         rts
  196.     @theTaskEnd
  197.         
  198.         ; VBL initialization code
  199.         lea        @theTaskEnd, a0        ; address of tail of task
  200.         lea        @theTaskBegin, a1    ; head of task
  201.         move.l    a1, taskAddress        ; head of task address into pointer variable
  202.         move.l    a0, d0                ; get size of task
  203.         sub.l    a1, d0
  204.         move.l    d0, taskSize
  205.         
  206.         lea        @A5Storage, a0        ; put current A5 into our storage area in code
  207.         move.l    CurrentA5, (a0)
  208.         }        
  209.  
  210.     gtheVBLPtr = NewPtr(sizeof(VBLTask));
  211.     gtheTaskPtr = NewPtr(taskSize);
  212.  
  213.     /* move the task code into block in System heap */
  214.     BlockMove(taskAddress, gtheTaskPtr, taskSize);
  215.  
  216.     asm {
  217.         move.l     gtheTaskPtr, a1
  218.         move.l    gtheVBLPtr, a0
  219.         move.l    a1, OFFSET(VBLTask, vblAddr)(a0)        ; a1 contains address of moved TheTask
  220.         move.w     #vType, OFFSET(VBLTask, qType)(a0)
  221.         move.w     #10, OFFSET(VBLTask, vblCount)(a0)
  222.         move.w     #4, OFFSET(VBLTask, vblPhase)(a0)
  223.         _VInstall
  224.         }
  225. }
  226.  
  227. stopAndDisposeSpinCursor()
  228. {
  229.     VRemove(gtheVBLPtr);
  230.     DisposPtr(gtheVBLPtr);
  231.     DisposPtr(gtheTaskPtr);
  232. }
  233. #endif
  234.  
  235.  
  236. /*
  237.  *    Draws an outline around the particular item in the dialog.
  238.  */
  239. void DrawBoldItem(WindowPtr whichWindow, short theItem, short whichStrID)
  240. {
  241.     Rect         r;
  242.     short        kind;
  243.     Handle        h;
  244.     Str255        str;
  245.     FontInfo    info;
  246.     
  247.     GetFontInfo(&info);
  248.     GetDItem(whichWindow, theItem, &kind, &h, &r);
  249.     TextFace(bold);
  250.     MoveTo(r.left, r.top + info.ascent);
  251.     GetIndString(str, kStringListID, whichStrID);
  252.     DrawString(str);
  253.     TextFace(0);
  254. }
  255.  
  256. /*
  257.  *    Main dialog handling routines for user item updating.  Here we'll update the 
  258.  *    two lists using _LUpdate and also draw a border around the list rectangles 
  259.  *    themselves.  We're actually drawing across the whole length of the content
  260.  *    region and not sure around the rView.  This is because the 6.x & older 
  261.  *    List Managers erase the region where the scoll bar use to be.  Since this
  262.  *    kinda bites we have to draw something to replace that whole.
  263.  *
  264.  *    Notice that the routine has to use Pascal calling conventions.
  265.  */
  266. pascal void updateUserItems(WindowPtr whichWindow, short theItem)
  267. {
  268.     GrafPtr     savedPort;
  269.     Rect         r;
  270.     
  271.     GetPort(&savedPort);
  272.     SetPort(whichWindow);
  273.  
  274.     switch(theItem) {
  275.         case kZoneListID:
  276.             LUpdate((*(**gZonesList).port).visRgn, gZonesList);
  277.             r = (**gZonesList).rView;
  278.             MoveTo(whichWindow->portRect.left, r.top-1);
  279.             LineTo(whichWindow->portRect.right, r.top-1);
  280.             MoveTo(whichWindow->portRect.left, r.bottom);
  281.             LineTo(whichWindow->portRect.right, r.bottom);
  282.             break;
  283.         case kNameTypeListID:
  284.             LUpdate((*(**gObjectTypeList).port).visRgn, gObjectTypeList);
  285.             r = (**gObjectTypeList).rView;
  286.             MoveTo(whichWindow->portRect.left, r.top-1);
  287.             LineTo(whichWindow->portRect.right, r.top-1);
  288.             MoveTo(whichWindow->portRect.left, r.bottom);
  289.             LineTo(whichWindow->portRect.right, r.bottom);
  290.             break;
  291.         case kZoneItemID:
  292.             DrawBoldItem(whichWindow, theItem, kZoneStrID);
  293.             break;
  294.         case kObjectID:
  295.             DrawBoldItem(whichWindow, theItem, kObjectStrID);
  296.             break;
  297.         case kTypeID:
  298.             DrawBoldItem(whichWindow, theItem, kTypeStrID);
  299.             break;
  300.         case kNetID:
  301.             DrawBoldItem(whichWindow, theItem, kNetStrID);
  302.             break;
  303.         case kNodeID:
  304.             DrawBoldItem(whichWindow, theItem, kNodeStrID);
  305.             break;
  306.         case kSocketID:
  307.             DrawBoldItem(whichWindow, theItem, kSktStrID);
  308.             break;
  309.         default:
  310.             break;
  311.         }
  312.     SetPort(savedPort);
  313. }
  314.     
  315. /* 
  316.  *    Generic routine for setting up dialog user items update procedure.  Saves us a 
  317.  *    few bytes by not duplicating the routine for each item.
  318.  */
  319. void getandSetIt(short whichID)
  320. {
  321.     Rect     r;
  322.     short    kind;
  323.     Handle    h;
  324.     static UserItemUPP    gUpdateUserItemsUPP = nil;
  325.     
  326.     GetDItem(gMyDialog, whichID, &kind, &h, &r);
  327.     
  328.     if (gUpdateUserItemsUPP==nil)
  329.         gUpdateUserItemsUPP = NewUserItemProc(updateUserItems);
  330.     SetDItem(gMyDialog, whichID, userItem, (Handle) gUpdateUserItemsUPP, &r);
  331. }
  332.     
  333. /* 
  334.  *    For each userItem in the list, we'll call getandSetIt() to set up the 
  335.  *    update procedure pointer.  We'll also set up the port's font & size here.
  336.  */
  337. void setupUserItems(void)
  338. {
  339.     GrafPtr savedPort;
  340.     
  341.     GetPort(&savedPort);
  342.     SetPort(gMyDialog);
  343.     
  344.     TextFont(monaco);
  345.     TextSize(9);
  346.     
  347.     getandSetIt(kZoneListID);
  348.     getandSetIt(kNameTypeListID);
  349.     getandSetIt(kZoneItemID);
  350.     getandSetIt(kObjectID);
  351.     getandSetIt(kTypeID);
  352.     getandSetIt(kNetID);
  353.     getandSetIt(kNodeID);
  354.     getandSetIt(kSocketID);
  355.     
  356.     SetPort(savedPort);
  357. }
  358.  
  359. /* 
  360.  *    This sets the value of the lookup item control to on
  361.  */
  362. void setupLookupItem(void)
  363. {
  364.     short        kind;
  365.     Handle        h;
  366.     Rect        r;
  367.  
  368.     GetDItem(gMyDialog, kDoLookupID, &kind, &h, &r);
  369.     SetCtlValue((ControlHandle)h, 1);
  370. }
  371.  
  372. /* 
  373.  *    This changes the current value of the gDoLookUp flag and reflects the state in the 
  374.  *    control
  375.  */
  376. void doLookupItem(void)
  377. {
  378.     short        kind;
  379.     Handle        h;
  380.     Rect        r;
  381.  
  382.     GetDItem(gMyDialog, kDoLookupID, &kind, &h, &r);
  383.     
  384.     gContLookUp ^= 1; /* assigns bitwise XOR (changes from on to off and visa versa) */
  385.  
  386.     SetCtlValue((ControlHandle)h, (short)gContLookUp);
  387. }
  388.  
  389. /*
  390.  *     Set the default state of a large window for zooming 
  391.  */
  392. void setWindowStdState(WindowPtr theWindow)
  393. {
  394.     Rect        wRect;
  395.     Point        tlP, brP;
  396.     GrafPtr        savePort;
  397.     
  398.     GetPort(&savePort);
  399.     SetPort(theWindow);
  400.     
  401.     /* 
  402.      *    set the userState - convert coords to globals 
  403.      */
  404.     tlP.h = theWindow->portRect.left;
  405.     tlP.v = theWindow->portRect.top;
  406.     brP.h = theWindow->portRect.right;
  407.  
  408. #ifdef THINK_C
  409.     brP.v = screenBits.bounds.bottom-45;
  410. #else
  411.     brP.v = qd.screenBits.bounds.bottom-45;
  412. #endif
  413.  
  414.     LocalToGlobal(&tlP);
  415.     LocalToGlobal(&brP);
  416.     
  417.     wRect.left = tlP.h;
  418.     wRect.top = tlP.v;
  419.     wRect.right = brP.h;
  420.     wRect.bottom = brP.v;
  421.     
  422.     (**(WStateData **) (*(WindowPeek)theWindow).dataHandle).stdState = wRect;
  423.  
  424.     SetPort(savePort);
  425. }
  426.  
  427.  
  428. /*
  429.  *     Create our one and only dialog from the DLOG resource.
  430.  *     If the DLOG resource isn't there, go wash your socks.
  431.  */
  432. void setUpDialogs(void)
  433. {
  434.  
  435.     /*
  436.      *    make sure there is a 'dctb' resource present so color stuff works!
  437.      */
  438.     gMyDialog = GetNewDialog(kMainDialogID, nil, (WindowPtr) -1);
  439.     gLookupDialog = GetNewDialog(kLookupDialogID, nil, (WindowPtr) -1);
  440.  
  441.     setWindowStdState(gMyDialog);
  442.     
  443.     setupUserItems();
  444. }
  445.  
  446. /* 
  447.  *    This frames the Object, type, etc. items in the main dialog window.  This tells the 
  448.  *    user which item the list is currently sorting on. The box size is based on the
  449.  *    size of the text itself and not on the dialog item rectangle size.  On a machine which
  450.  *    supports color, we'll use RGB value form HiliteRGB for the outline box color. No need
  451.  *    for this utlity to use stodgy old black and white if it doesn' t have too.. And it 
  452.  *    also adds some uniformity to the selection idea since the lists also use HiliteRGB.
  453.  *    One thing we do not do with the selection is remove it if window is in background...
  454.  *    ...should we to be truley HIG compatible?
  455.  */
  456. void FrameItem(DialogPtr whichDialog, short whichItem)
  457. {
  458.     short        kind;
  459.     Handle        h;
  460.     Rect        r;
  461.     PenState    ps;
  462.     RGBColor    rgb, curRGB;
  463.     unsigned char    str[10];
  464.     FontInfo    info;
  465.     short        strListID;
  466.     GrafPtr        savePort;
  467.     
  468.     GetPort(&savePort);
  469.     SetPort(whichDialog);
  470.     
  471.     TextFace(bold);
  472.  
  473.     /* 
  474.      *    unframe old item 
  475.      */
  476.     GetDItem(whichDialog, gSortItem, &kind, &h, &r);
  477.     
  478.     switch (gSortItem) {
  479.         case kObjectID:
  480.             strListID = kObjectStrID;
  481.             break;
  482.         case kTypeID:
  483.             strListID = kTypeStrID;
  484.             break;
  485.         case kNetID:
  486.             strListID = kNetStrID;
  487.             break;
  488.         case kNodeID:
  489.             strListID = kNodeStrID;
  490.             break;
  491.         case kSocketID:
  492.             strListID = kSktStrID;
  493.             break;
  494.         }
  495.         
  496.     GetIndString(str, kStringListID, strListID);
  497.     GetPenState(&ps);
  498.  
  499.     PenPat(&qd.white);
  500.     GetFontInfo(&info);
  501.     r.right = r.left + StringWidth(str) + 2;
  502.     r.left -= 2;
  503.     r.bottom = r.top;
  504.     r.bottom += info.ascent + info.descent + 2;    
  505.     r.top -= 1;
  506.     FrameRect(&r);
  507.     SetPenState(&ps);
  508.  
  509.     /* 
  510.      *    If Color QD is present, we will change the foreground color to HiliteRGB
  511.      *    so that our "selection" frame will match our list's hilites.
  512.      */
  513.     if(GMAC.hasColorQD) {
  514.         BlockMove((Ptr) HiliteRGB,(Ptr)  &rgb, sizeof(RGBColor));
  515.         GetForeColor(&curRGB);
  516.         RGBForeColor(&rgb);
  517.     }
  518.  
  519.     /* 
  520.      *    frame new item 
  521.      */
  522.     switch (whichItem) {
  523.         case kObjectID:
  524.             strListID = kObjectStrID;
  525.             break;
  526.         case kTypeID:
  527.             strListID = kTypeStrID;
  528.             break;
  529.         case kNetID:
  530.             strListID = kNetStrID;
  531.             break;
  532.         case kNodeID:
  533.             strListID = kNodeStrID;
  534.             break;
  535.         case kSocketID:
  536.             strListID = kSktStrID;
  537.             break;
  538.         }
  539.         
  540.     GetDItem(whichDialog, whichItem, &kind, &h, &r);
  541.     GetIndString(str, kStringListID, strListID);
  542.  
  543.     GetFontInfo(&info);
  544.     r.right = r.left + StringWidth(str) + 2;
  545.     r.left -= 2;
  546.     r.bottom = r.top;
  547.     r.bottom += info.ascent + info.descent + 2;    
  548.     r.top -= 1;
  549.     FrameRect(&r);
  550.     
  551.     TextFace(0);
  552.  
  553.     /* 
  554.      *    Reset foreground color.
  555.      */
  556.     if(GMAC.hasColorQD)
  557.         RGBForeColor(&curRGB);
  558.     
  559.     gSortItem = whichItem;
  560.  
  561.     SetPort(savePort);
  562. }
  563.  
  564. /* 
  565.  *    This is the routine called by _DialogSelect.  It handles all userItem events
  566.  *    except updating.
  567.  */
  568. void doModeless(DialogPtr whichDialog, short whichItem)
  569. {        
  570.     if(whichDialog == gMyDialog) {
  571.         switch(whichItem) {
  572.             case kZoneListID: /* 1 */
  573.                 doZonesListStuff();
  574.                 break;
  575.             case kNameTypeListID: /* 2 */
  576.                  doObjectTypeListStuff();
  577.                  break;
  578.             case kObjectID:
  579.                 gSortMode = sortOnObject;
  580.                 FrameItem(whichDialog, whichItem);
  581.                 getTypesNamesInZone(gNameGlob);
  582.                 break;
  583.             case kTypeID:
  584.                 gSortMode = sortOnType;
  585.                 FrameItem(whichDialog, whichItem);
  586.                 getTypesNamesInZone(gNameGlob);
  587.                 break;
  588.             case kNetID:
  589.                 gSortMode = sortOnNet;
  590.                 FrameItem(whichDialog, whichItem);
  591.                 getTypesNamesInZone(gNameGlob);
  592.                 break;
  593.             case kNodeID:
  594.                 gSortMode = sortOnNode;
  595.                 FrameItem(whichDialog, whichItem);
  596.                 getTypesNamesInZone(gNameGlob);
  597.                 break;
  598.             case kSocketID:    
  599.                 gSortMode = sortOnSocket;
  600.                 FrameItem(whichDialog, whichItem);
  601.                 getTypesNamesInZone(gNameGlob);
  602.                 break;
  603.             default:
  604.                 break;
  605.             }
  606.     }
  607. }
  608.         
  609. /*    
  610.  *    doIdle()  Called repeatedly in main event loop for cursor tasks
  611.  *    and NBPLookups.
  612.  */
  613. void doIdle(void)     
  614. {
  615.     if(gUpdateListFlag == true) {
  616.         processListUpdate();
  617.     }
  618. }
  619.  
  620. /* 
  621.  *    draws the grow box 
  622.  */ 
  623. void DrawGrowBox(WindowPtr theWindow)
  624. {
  625.     Rect        r, windowRect;
  626.     GrafPtr        tempPort;
  627.     
  628.     /*
  629.      *    copy theWindow->portRect into a local rect for efficency.  
  630.      *    no need to dereference theWindow all the time.
  631.      */
  632.     GetPort(&tempPort);
  633.     SetPort(theWindow);
  634.     
  635.     windowRect = theWindow->portRect;
  636.     
  637.     if(((WindowPeek)theWindow)->hilited) {
  638.         MoveTo(windowRect.right-12, windowRect.bottom-12);
  639.         LineTo(windowRect.right-6, windowRect.bottom-12);
  640.         LineTo(windowRect.right-6, windowRect.bottom-6);
  641.         LineTo(windowRect.right-12, windowRect.bottom-6);
  642.         LineTo(windowRect.right-12, windowRect.bottom-12);
  643.     
  644.         MoveTo(windowRect.right-5, windowRect.bottom-10);
  645.         LineTo(windowRect.right-2, windowRect.bottom-10);
  646.         LineTo(windowRect.right-2, windowRect.bottom-2);
  647.         LineTo(windowRect.right-10, windowRect.bottom-2);
  648.         LineTo(windowRect.right-10, windowRect.bottom-5);
  649.         }
  650.     else {
  651.         SetRect(&r, windowRect.right-17, windowRect.bottom-15,
  652.             windowRect.right, windowRect.bottom);
  653.         EraseRect(&r);
  654.         }
  655.  
  656.     MoveTo(windowRect.right-15, windowRect.bottom);
  657.     LineTo(windowRect.right-15, windowRect.bottom-15);
  658.     MoveTo(windowRect.right-15, windowRect.bottom-15);
  659.     LineTo(windowRect.right, windowRect.bottom-15);
  660.  
  661.     SetPort(tempPort);
  662. }
  663.  
  664. /* 
  665.  *    updates the gSortItem rectangle 
  666.  */
  667. void doUpdate(WindowPtr theWindow)
  668. {
  669.     RGBColor    rgb, curRGB;
  670.     
  671.     if(theWindow == gMyDialog) 
  672.     {
  673.         if(GMAC.hasColorQD) 
  674.         {
  675.             BlockMove((Ptr) HiliteRGB, (Ptr) &rgb, sizeof(RGBColor));
  676.             GetForeColor(&curRGB);
  677.             RGBForeColor(&rgb);
  678.         }
  679.     
  680.         FrameItem(gMyDialog, gSortItem);
  681.         if(GMAC.hasColorQD)
  682.             RGBForeColor(&curRGB);
  683.         DrawGrowBox(theWindow);
  684.     }
  685. }
  686.  
  687.  
  688. /*    
  689.  *    ShowMainWindowAndSizeIt() opens our main window to the size of our main screen
  690.  *    and displays it.
  691.  */
  692. void ShowMainWindowAndSizeIt(void)
  693. {
  694.     extern void DoZoomWindow(WindowPtr whichWindow, short partCode);
  695.     
  696.     /*
  697.      *    show it…
  698.      */
  699.     ShowWindow(gMyDialog);
  700.     
  701.     /*
  702.      *    and resize it.
  703.      */
  704.     /* DoZoomWindow(gMyDialog, inZoomOut); */
  705. }
  706.  
  707.  
  708. /*    
  709.  *    doInitializing() Called at application boot to allocate master pointers,
  710.  *    check SysEnvirons() for Mac type, check for WaitNextEvent implementation.
  711.  *    and call all other initializing routines.
  712.  */
  713. void doInitializing(void)
  714. {
  715.     extern        void setupMenus();
  716.     OSErr        ignoreError, err;
  717.     CursHandle    theWatch;
  718.     short        count;
  719.     
  720.     /*
  721.      * Initialization traps
  722.      */
  723.     MaxApplZone();
  724.  
  725.     MoreMasters();
  726.     MoreMasters();
  727.     MoreMasters();
  728.     MoreMasters();
  729.     
  730.     /* 
  731.      *    ignore the error returned from SysEnvirons; even if an error occurred,
  732.      *    the SysEnvirons glue will fill in the SysEnvRec 
  733.      */
  734.     ignoreError = SysEnvirons(sysEnvironsVersion, &GMAC);
  735.     if ( GMAC.machineType < 0 )                 /*old machines have...*/ 
  736.         gHasWaitNextEvent = false;             /*no separate trap table; no WaitNextEvent */
  737.     else
  738.         gHasWaitNextEvent = TrapAvailable(_WaitNextEvent);
  739.  
  740.     gInBackground = false;
  741.  
  742. #ifdef THINK_C
  743.     InitGraf(&thePort);
  744. #else
  745.     InitGraf(&qd.thePort);
  746. #endif
  747.     
  748.     InitFonts();
  749.     FlushEvents(everyEvent, 0);
  750.     InitWindows();
  751.     InitMenus();
  752.     InitDialogs(0L);    
  753.  
  754.     /*    
  755.      *    This next bit of code is necessary to allow the default button of our
  756.      *    alert be outlined.
  757.      *    Changed to call _EventAvail so that we don't lose some important
  758.      *    events. 
  759.      */     
  760.     for (count = 1; count <= 3; count++) {
  761.         EventAvail(everyEvent, &gMyEvent);
  762.     }
  763.  
  764.     /* 
  765.      *    make 'em wait 
  766.      */
  767.     theWatch = GetCursor(watchCursor);    
  768.     SetCursor(*theWatch);
  769.  
  770.     /* 
  771.      *    setupmenus 
  772.      */
  773.     setupMenus();            
  774.  
  775.     /*
  776.      * setup the dialog.
  777.      */
  778.     setUpDialogs();
  779.     SetPort(gMyDialog);
  780.     
  781.     /*
  782.      * is VM on
  783.      * this must be determined before calling InitEchoBuffers which gets called from
  784.      * InitAppleTalkVars
  785.      */
  786.     if (IsVMOn())
  787.         gATalkFlags |= (1 << kVMActive);
  788.     
  789.     /*
  790.      * setup the list stuff.
  791.      */
  792.     OpenZonesList();
  793.     OpenObjectTypeList();
  794.  
  795.     /*
  796.      * initialize assorted and sundry variables
  797.      */
  798.     gDoneFlag = false;
  799.     gNameGlob[0] = 0;
  800.     gUpdateListFlag = false;
  801.     gLookupFinished = true;
  802.     gSortMode = sortOnObject;
  803.  
  804.         // allocate memory for our globals
  805.     gATQEntry.globs = NewHandleClear(sizeof(myATQEntry));
  806.     if (gATQEntry.globs == nil) 
  807.     {
  808.         BigBadError("\pError allocating memory - Aborting program");
  809.     }
  810.     
  811.     /*
  812.      * install our tranisiton queue handler
  813.      */
  814.     if (LAPMgrExists()) 
  815.     {
  816.  
  817.         gATQEntry.myA5 = (long)LMGetCurrentA5(); /* get the Current A5 */
  818.             
  819.         gAtalkTransUPP = NewATalkTransitionEventProc(ATalkTransQueue);
  820.         gATQEntry.CallAddr = gAtalkTransUPP;
  821.         err = LAPAddATQ((ATQEntry*)&gATQEntry);
  822.         if (err == noErr) 
  823.         {
  824.             gATalkFlags |= (1 << kATQInstalled);        /* indicate that the trans queue was installed */
  825.         }
  826.         else
  827.             BigBadError("\pError setting up AppleTalk - Aborting program");
  828.     }
  829.     else
  830.     {
  831.         BigBadError("\pThis program requires AppleTalk version 53 or greater");
  832.     }
  833.     
  834.     
  835.     
  836.     /*
  837.      * setup the appletalk stuff.
  838.      */
  839.     InitAppleTalkVars();
  840.  
  841.     /*
  842.      * open the main window & size it to the main screen.
  843.      */
  844.     ShowMainWindowAndSizeIt();
  845.         
  846.     InitCursor();
  847. }
  848.     
  849. /*
  850.  *    uses predefined value to calculate 'grid height' of list.
  851.  */
  852. short resizeRectToListCellSize(short height)
  853. {
  854.     short    temp;
  855.  
  856.     height -= 113;
  857.     temp = height % 11;
  858.     height += (113 - temp);
  859.  
  860.     return height;
  861. }
  862.  
  863. void resizeWindow(WindowPtr whichWindow, short height)
  864. {
  865.     short        kind;
  866.     Handle        h;
  867.     Rect            r;
  868.     RgnHandle    savedClipRgn, theListMgrSucksRgn;
  869.  
  870.     /*
  871.      *    this 'grids' the bottom of the window to the right height to fit the list cell size
  872.      */
  873.     SizeWindow(whichWindow, whichWindow->portRect.right-whichWindow->portRect.left, height, true);
  874.  
  875.     GetDItem(gMyDialog, kNameTypeListID, &kind, &h, &r);
  876.     
  877.     savedClipRgn = NewRgn();
  878.     theListMgrSucksRgn = NewRgn();
  879.     GetClip(savedClipRgn);
  880.     SetClip(theListMgrSucksRgn);
  881.     
  882.     r.bottom = whichWindow->portRect.bottom;
  883.     SetDItem(gMyDialog, kNameTypeListID, kind, h, &r);
  884.     
  885.     LSize((**gObjectTypeList).rView.right-(**gObjectTypeList).rView.left, (whichWindow->portRect.bottom)-(**gObjectTypeList).rView.top, gObjectTypeList);
  886.  
  887.     SizeControl((**gObjectTypeList).vScroll, (**(**gObjectTypeList).vScroll).contrlRect.right - 
  888.         (**(**gObjectTypeList).vScroll).contrlRect.left, (**(**gObjectTypeList).vScroll).contrlRect.bottom - 
  889.         (**(**gObjectTypeList).vScroll).contrlRect.top - 15);
  890.  
  891.     SetClip(savedClipRgn);
  892.     DisposeRgn(savedClipRgn);
  893.     DisposeRgn(theListMgrSucksRgn);
  894.  
  895.     /*
  896.      *    Erase grow box icon
  897.      */
  898.     SetRect(&r, whichWindow->portRect.right-14, whichWindow->portRect.bottom-15, 
  899.         whichWindow->portRect.right, whichWindow->portRect.bottom);
  900.     EraseRect(&r);
  901. }
  902.  
  903. /*    
  904.  *    Check to see if a window belongs to the application. If the window pointer
  905.  *    passed was NIL, then it could not be an application window. WindowKinds
  906.  *    that are negative belong to the system and windowKinds less than userKind
  907.  *    are reserved by Apple except for windowKinds equal to dialogKind, which
  908.  *    mean it is a dialog.
  909.  *    1.02 - In order to reduce the chance of accidentally treating some window
  910.  *    as an AppWindow that shouldn't be, we'll only return true if the windowkind
  911.  *    is userKind. If you add different kinds of windows to Sample you'll need
  912.  *    to change how this all works. 
  913.  */
  914.  
  915. Boolean IsAppWindow(WindowPtr window)
  916. {
  917.     short        windowKind;
  918.  
  919.     if ( window == nil )
  920.         return false;
  921.     else {    /* application windows have windowKinds = userKind (8) */
  922.         windowKind = ((WindowPeek) window)->windowKind;
  923.         return (windowKind == userKind);
  924.     }
  925. } /*IsAppWindow*/
  926.  
  927.  
  928. /* Check to see if a window belongs to a desk accessory. */
  929.  
  930. Boolean IsDAWindow(WindowPtr window)
  931. {
  932.     if ( window == nil )
  933.         return false;
  934.     else    /* DA windows have negative windowKinds */
  935.         return ((WindowPeek) window)->windowKind < 0;
  936. } /*IsDAWindow*/
  937.  
  938.  
  939. /* Close a window. This handles desk accessory and application windows. */
  940.  
  941. /*    
  942.  *    1.01 - At this point, if there was a document associated with a
  943.  *    window, you could do any document saving processing if it is 'dirty'.
  944.  *    DoCloseWindow would return true if the window actually closed, i.e.,
  945.  *    the user didn’t cancel from a save dialog. This result is handy when
  946.  *    the user quits an application, but then cancels the save of a document
  947.  *    associated with a window. 
  948.  */
  949.  
  950. Boolean DoCloseWindow(WindowPtr window)
  951. {
  952.     if ( IsDAWindow(window) )
  953.         CloseDeskAcc(((WindowPeek) window)->windowKind);
  954.     else if ( window == gLookupDialog ) {
  955.         HideWindow(window);
  956.     }
  957.     return true;
  958. } /*DoCloseWindow*/
  959.  
  960.  
  961. /*
  962.  *    The USER, let's call him "Bob", has clicked in the zoom box so now he, "Bob", probably expects
  963.  *    us to do something about it.
  964.  */
  965.  
  966. void DoZoomWindow(WindowPtr whichWindow, short partCode)
  967. {
  968.     WindowPeek        wp;
  969.     WStateData        **wStateH;
  970.     Rect            globalPortRect, theSect, zoomRect;
  971.     GDHandle        nthDevice, dominantGDevice;
  972.     long            sectArea, greatestArea;
  973.     short            bias;
  974.     Boolean            sectFlag;
  975.     short            windowHeight, windowWidth;
  976.     
  977.     wp = (WindowPeek) whichWindow;
  978.  
  979.     SetPort(whichWindow);
  980.     EraseRect(&whichWindow->portRect);
  981.     
  982.     wStateH = (WStateData **)wp->dataHandle;
  983.  
  984.     if(partCode == inZoomOut) {
  985.         if(GMAC.hasColorQD) {
  986.             /* 
  987.                *    Get the width of our window for later use. 
  988.                */
  989.             windowWidth = whichWindow->portRect.right - whichWindow->portRect.left;
  990.  
  991.             /* 
  992.                *    window's portRect must be converted to global coordinates... a pain in C...
  993.                */
  994.             globalPortRect = (**(*(WindowPeek)whichWindow).strucRgn).rgnBBox; /*whichWindow->portRect;*/
  995.             
  996.             /*
  997.             pt.h = globalPortRect.left;
  998.             pt.v = globalPortRect.top;
  999.             LocalToGlobal(&pt);
  1000.             globalPortRect.left = pt.h;
  1001.             globalPortRect.top = pt.v;
  1002.     
  1003.             pt.h = globalPortRect.right;
  1004.             pt.v = globalPortRect.bottom;
  1005.             LocalToGlobal(&pt);
  1006.             globalPortRect.right = pt.h;
  1007.             globalPortRect.bottom = pt.v;
  1008.             */
  1009.  
  1010.             /*
  1011.              *    Now let's calculate the height of the window's title bar 
  1012.              */
  1013.             bias = (**(*(WindowPeek)whichWindow).contRgn).rgnBBox.top -
  1014.                 (**(*(WindowPeek)whichWindow).strucRgn).rgnBBox.top - 1; 
  1015.             
  1016.             nthDevice = GetDeviceList();
  1017.  
  1018.             /*
  1019.              *    This loop checks the window against all the gdRects in the   
  1020.              *    gDevice list and remembers which gdRect contains the largest 
  1021.              *    portion of the window being zoomed. 
  1022.              */
  1023.             greatestArea = 0;
  1024.             while(nthDevice != 0L) {
  1025.                 sectFlag = SectRect(&globalPortRect, &(**nthDevice).gdRect, &theSect);
  1026.                 sectArea = (long)(theSect.right - theSect.left) * (theSect.bottom - theSect.top);
  1027.                 if(sectArea > greatestArea) {
  1028.                     greatestArea = sectArea;
  1029.                     dominantGDevice = nthDevice;
  1030.                     }
  1031.                 nthDevice = GetNextDevice(nthDevice);
  1032.                 } 
  1033.             
  1034.             /*
  1035.              *    We must create a zoom rectangle manually in this case. 
  1036.              *    account for menu bar height as well, if on main device 
  1037.              */
  1038.             if (dominantGDevice == GetMainDevice()) 
  1039.                 bias = bias + GetMBarHeight();
  1040.               
  1041.             /*
  1042.              *    Now let's set our newly discovered 'zoom' rectangle. 3 is the recommend inset
  1043.              *    value from the device's boundries.
  1044.              */
  1045.             SetRect(&zoomRect,(**dominantGDevice).gdRect.left+3,(**dominantGDevice).gdRect.top+bias+3,
  1046.                 (**dominantGDevice).gdRect.right-3,(**dominantGDevice).gdRect.bottom-3);
  1047.               
  1048.             /*
  1049.              *    Set up the WStateData record for this window. 
  1050.              */
  1051.             (**wStateH).stdState = zoomRect;
  1052.             windowHeight = zoomRect.bottom-zoomRect.top;
  1053.  
  1054.             /*
  1055.              *    Resize the bottom coordinate based on the size of a cell for neatness. 
  1056.              */
  1057.             (**wStateH).stdState.bottom = zoomRect.top + resizeRectToListCellSize(windowHeight);
  1058.             
  1059.             /*
  1060.              *    We have a fixed width for our window.  Reset it now. 
  1061.              */
  1062.             (**wStateH).stdState.right = (**wStateH).stdState.left + windowWidth;
  1063.             }
  1064.         else {
  1065.             /*
  1066.              *    We (probably) only have one device so this is all we need to do. 
  1067.              */
  1068. #ifdef THINK_C
  1069.             windowHeight = screenBits.bounds.bottom-7-(**wStateH).stdState.top;
  1070. #else
  1071.             windowHeight = qd.screenBits.bounds.bottom-7-(**wStateH).stdState.top;
  1072. #endif
  1073.             (**wStateH).stdState.bottom = (**wStateH).stdState.top + resizeRectToListCellSize(windowHeight);
  1074.             }
  1075.         }
  1076.         
  1077.     ZoomWindow(whichWindow, partCode, true);
  1078.     resizeWindow(whichWindow, (short) (whichWindow->portRect.bottom-whichWindow->portRect.top));
  1079. }
  1080.  
  1081. void DoGrowWindow(WindowPtr whichWindow, EventRecord    *evt)
  1082. {
  1083.     Rect        limitRect;
  1084.     long        newSize;
  1085.     GrafPtr        savePort;
  1086.     short        height;
  1087.     
  1088.     GetPort(&savePort);
  1089.     
  1090. #ifdef THINK_C
  1091.     limitRect = screenBits.bounds;
  1092. #else
  1093.     limitRect = qd.screenBits.bounds;
  1094. #endif
  1095.  
  1096.     SetPort(whichWindow);
  1097.  
  1098.     limitRect.right = whichWindow->portRect.right + 1;
  1099.     limitRect.left = whichWindow->portRect.right + 1;
  1100.     limitRect.top = whichWindow->portRect.top + 203;
  1101.     
  1102.     newSize = GrowWindow(whichWindow, evt->where, &limitRect);
  1103.  
  1104.     if(newSize != 0L) {
  1105.         /* 
  1106.          *    set to our dialog, erase the content region and re-size the window
  1107.          */
  1108.         /* SizeWindow(whichWindow, LoWord(newSize), height, true);*/
  1109.         height = HiWord(newSize);
  1110.         height = resizeRectToListCellSize(height);
  1111.         resizeWindow(whichWindow, height);
  1112.         }
  1113.  
  1114.     SetPort(savePort);
  1115. }
  1116.  
  1117. void main(void)
  1118. {
  1119.     WindowPtr            whichWindow;
  1120.     DialogPtr            whichDialog;
  1121.     short                 whichItem;
  1122.     extern     void         doCommand();
  1123.     extern  void         doCleanUpAndTerminate();
  1124.     extern     void         doActivate();
  1125.     extern  void         doDeactivate();
  1126.     Boolean                processIt;
  1127.     short                partCode;
  1128.     EventRecord            myEvent;
  1129.         
  1130.     doInitializing();
  1131.     
  1132.     for ( ;; ) {
  1133.         if (gDoneFlag) 
  1134.             break;        /* from main event loop */
  1135.             
  1136.         if ( gHasWaitNextEvent ) 
  1137.             /* 
  1138.              *    no sleeping for us... 
  1139.              */
  1140.             processIt = WaitNextEvent(everyEvent, &myEvent, 0L, 0L);
  1141.         else {
  1142.             SystemTask();
  1143.             processIt = GetNextEvent(everyEvent, &myEvent);
  1144.             }
  1145.  
  1146.         /* 
  1147.          *    this checks to make sure we don't pass any cmd key events to the 
  1148.          *    modeless dialog.  This must be called even if the event traps
  1149.          *    return false for text edit idling.
  1150.          */
  1151.         /*
  1152.         if(!((myEvent.what==keyDown)&&(gMyEvent.modifiers & cmdKey))) {
  1153.             if (!((gMyEvent.what==keyDown)&&((char)(gMyEvent.message & charCodeMask))>'9')
  1154.             &&!((gMyEvent.what==keyDown)&&((char)(gMyEvent.message & charCodeMask))<(char)8)) {
  1155.                 if(IsDialogEvent(&gMyEvent)) {
  1156.                     if(DialogSelect(&gMyEvent, &whichDialog, &whichItem))
  1157.                         doModeless(whichDialog, whichItem);
  1158.                 }
  1159.             }
  1160.         }
  1161.         */
  1162.         
  1163.         if(!(myEvent.modifiers & cmdKey)) {
  1164.             if(IsDialogEvent(&myEvent)) {
  1165.                 if(DialogSelect(&myEvent, &whichDialog, &whichItem))
  1166.                     doModeless(whichDialog, whichItem);
  1167.             }
  1168.         }
  1169.         gMyEvent = myEvent;
  1170.         
  1171.         /*
  1172.         if(IsDialogEvent(&myEvent)) {
  1173.             if(DialogSelect(&myEvent, &whichDialog, &whichItem)) {
  1174.                 if(whichDialog == gMyDialog)
  1175.                     doModeless(whichDialog, whichItem);    
  1176.                 }
  1177.         }
  1178.         */
  1179.         
  1180.          {    
  1181.             switch (myEvent.what) 
  1182.             {    
  1183.                 case nullEvent:
  1184.                     doIdle();
  1185.                     break;
  1186.                                 
  1187.                 case mouseDown:
  1188.                     partCode = FindWindow(myEvent.where, &whichWindow);
  1189.                     switch (partCode) 
  1190.                         {
  1191.                         case inSysWindow:
  1192.                             SystemClick(&myEvent, whichWindow);
  1193.                             break;
  1194.     
  1195.                         case inMenuBar:
  1196.                             doCommand(MenuSelect(myEvent.where));
  1197.                             break;
  1198.     
  1199.                         case inDrag:
  1200.                             #ifdef THINK_C
  1201.                                 DragWindow(whichWindow, myEvent.where, &screenBits.bounds);
  1202.                             #else
  1203.                                 DragWindow(whichWindow, myEvent.where, &qd.screenBits.bounds);
  1204.                             #endif
  1205.                             break;
  1206.     
  1207.                         case inGoAway:
  1208.                             if (TrackGoAway(whichWindow, myEvent.where))
  1209.                                 DoCloseWindow(whichWindow);             /* we don’t care if the user cancelled */
  1210.                             break;
  1211.     
  1212.                         case inGrow:
  1213.                             DoGrowWindow(whichWindow, &myEvent);
  1214.                             break;
  1215.     
  1216.                         case inContent:
  1217.                             if(whichWindow != FrontWindow())
  1218.                                 SelectWindow(whichWindow);
  1219.                             break;
  1220.     
  1221.                         case inZoomIn:
  1222.                         case inZoomOut:
  1223.                             if(whichWindow == FrontWindow()) {
  1224.                                 if(TrackBox(whichWindow, myEvent.where, partCode)) 
  1225.                                     DoZoomWindow(whichWindow, partCode);
  1226.                                 }
  1227.                             break;
  1228.     
  1229.                         default:
  1230.                             break;
  1231.                         }
  1232.                     break;
  1233.     
  1234.                 case keyDown:
  1235.                 case autoKey:
  1236.                     if (gMyDialog == FrontWindow()) {
  1237.                         if (myEvent.modifiers & cmdKey) 
  1238.                             doCommand(MenuKey(myEvent.message & charCodeMask));
  1239.                         else if ((myEvent.message & charCodeMask) == kEnterKey
  1240.                             || (myEvent.message & charCodeMask) == kReturnKey)
  1241.                             doObjectDoubleClick();
  1242.                         }
  1243.                     else if (gLookupDialog == FrontWindow())
  1244.                         if (myEvent.modifiers & cmdKey) 
  1245.                             doCommand(MenuKey(myEvent.message & charCodeMask));
  1246.                     break;
  1247.     
  1248.                 case activateEvt:
  1249.                     if ((WindowPtr) myEvent.message == gMyDialog || (WindowPtr) myEvent.message == gLookupDialog) {
  1250.                         if (myEvent.modifiers & activeFlag) {
  1251.                             if ((WindowPtr) myEvent.message == gMyDialog)
  1252.                                 doActivate(gMyDialog);                        
  1253.                             DisableItem(GetMHandle(editID), 0);
  1254.                         } 
  1255.                         else {
  1256.                             if ((WindowPtr) myEvent.message == gMyDialog)
  1257.                                 doDeactivate(gMyDialog);                        
  1258.                             if(FrontWindow() != gMyDialog && FrontWindow() != gLookupDialog)
  1259.                                 EnableItem(GetMHandle(editID), 0);
  1260.                         }
  1261.                     }
  1262.                     DrawMenuBar();
  1263.                     break;
  1264.     
  1265.                 case updateEvt:
  1266.                     /* 
  1267.                      *    all our updating is handled by the Dialog Mananger
  1268.                      *     and our userItem update routines.
  1269.                      */
  1270.                      doUpdate((WindowPtr) myEvent.message);
  1271.                      break;
  1272.     
  1273.                 case osEvt:
  1274.                     switch (myEvent.message >> 24) {     /* high byte of message */
  1275.                         case mouseMovedMessage:
  1276.                             doIdle();    /* mouse moved is also an idle event */
  1277.                             break;
  1278.                         case suspendResumeMessage:
  1279.                             if ( myEvent.message & resumeMask ) {
  1280.                                 /* 
  1281.                                  *    resume event received  
  1282.                                  *  check first whether an ATalk Queue Event has occured
  1283.                                  */
  1284.                                 if (((dmzEntryPtr) *(gATQEntry.globs))->atalkStatusChanged) 
  1285.                                 {
  1286.                                     ((dmzEntryPtr) *(gATQEntry.globs))->atalkStatusChanged = false;   /* clears the changed bit */
  1287.                                     if (((dmzEntryPtr) *(gATQEntry.globs))->atalkActive) 
  1288.                                     {
  1289.                                         InitAppleTalkVars();
  1290.                                         invalidateItem(1);
  1291.                                     }
  1292.                                     else     // AppleTalk has become inactive
  1293.                                     {
  1294.                                         ClearZoneCells();
  1295.                                         ClearObjectTypesList();
  1296.                                         tellUserNoZones();
  1297.                                     }
  1298.                                 }
  1299.                                 else
  1300.                                     enableSetSelfSend();
  1301.                                 doActivate(gMyDialog);
  1302.                                 gInBackground = false;
  1303.                             } else {
  1304.                                 /* 
  1305.                                  *    suspend event received
  1306.                                  */
  1307.                                 restoreSetSelfSend();
  1308.                                 doDeactivate(gMyDialog);
  1309.                                 gInBackground = true;
  1310.                                 }
  1311.                             DrawMenuBar();
  1312.                             break;
  1313.                         }
  1314.                     break;
  1315.                 }/*endsw myEvent.what*/
  1316.             }
  1317.         }
  1318.  
  1319.     doCleanUpAndTerminate();
  1320. }
  1321.  
  1322. /*
  1323.  *     Handle any activate routines here.  In our case this mean activating the lists and redrawing
  1324.  *    our grow box.
  1325.  */
  1326. void doActivate(WindowPtr theWindow)
  1327. {
  1328.     /* 
  1329.      *    Hilites scroll bars and updates scrollbar control max fields with _LActivate(true, ...).
  1330.      */
  1331.     LActivate(true, gZonesList);
  1332.     LActivate(true, gObjectTypeList);
  1333.  
  1334.     /*     
  1335.      *    this is like really dumb but necessary for ListManager
  1336.      *    skankiness.  It forces the lists's scroll bar's to
  1337.      *    recalculate & update which is not handled by _LActivate.
  1338.  
  1339.     LUpdate((*(**gZonesList).port).visRgn, gZonesList);
  1340.     LUpdate((*(**gObjectTypeList).port).visRgn, gObjectTypeList);
  1341.     */
  1342.  
  1343.     DrawGrowBox(theWindow);
  1344. }
  1345.     
  1346. /*
  1347.  * 
  1348.  */
  1349. void doDeactivate(WindowPtr    theWindow)
  1350. {
  1351.     /* 
  1352.      *    instead of only calling _LActivate(false, ...), we're going to unhilite 
  1353.      *    the two scroll bars too.  _LActivate(false, ...) actually hides the WHOLE 
  1354.      *    scroll bar control, outline and all, which isn't really to Human Interface 
  1355.      *    Guidelines or Pete's Mom's Prairie Home Programming Rules.  Besides it 
  1356.      *    looks really silly.
  1357.      *
  1358.      *  If you want to use the LActivate instead substitute the following lines
  1359.      *    for the HilitControl and the LActivate flag lines.
  1360.      *    2/17/90 pvh - forget it.  just use the LActivate call instead.  toolbox wins.
  1361.      */
  1362.     
  1363.     LActivate(false, gZonesList);
  1364.     LActivate(false, gObjectTypeList);
  1365.     
  1366.     /*
  1367.     (**gZonesList).lActive = false;
  1368.     (**gObjectTypeList).lActive = false;
  1369.     HiliteControl((**gZonesList).vScroll, 255);
  1370.     HiliteControl((**gObjectTypeList).vScroll, 255);
  1371.     ShowControl((**gZonesList).vScroll);
  1372.     ShowControl((**gObjectTypeList).vScroll);
  1373.     */
  1374.  
  1375.     DrawGrowBox(theWindow);
  1376. }
  1377.     
  1378. /*
  1379.  * Cleanup here.  Calls all clean up routines.
  1380.  */
  1381. void doCleanUpAndTerminate(void)
  1382. {
  1383.     closeUpOurAppleTalk();
  1384.     HideWindow(gMyDialog);
  1385.     DisposOfMyLists();
  1386.     DisposDialog(gMyDialog);
  1387.     
  1388.     ExitToShell();
  1389. }
  1390.     
  1391. /*
  1392.  * Set up the Apple, File, and Edit menus using the MBAR resource.
  1393.  * If the MENU resources are missing, we die and find something better to do.
  1394.  */
  1395. void setupMenus(void)
  1396. {
  1397.     Handle        myMenuBar;
  1398.     
  1399.     myMenuBar = GetNewMBar(128);
  1400.     SetMenuBar(myMenuBar);
  1401.     DisposHandle(myMenuBar);
  1402.     AddResMenu(GetMHandle(appleID), 'DRVR');
  1403.     
  1404.     DrawMenuBar();
  1405. }
  1406.  
  1407. /*
  1408.  * The user has tried to cut, copy or paste into the lookup dialog.
  1409.  * We'll try to handle that here.
  1410.  */
  1411. void handleLookupDialogEdit(void)
  1412. {
  1413. }
  1414.  
  1415.     
  1416. /*
  1417.  * Process mouse clicks in menu bar
  1418.  */
  1419. void doCommand(mResult)
  1420.     long    mResult;
  1421.     {
  1422.     int                 theMenu, theItem;
  1423.     Str255                daName;
  1424.     GrafPtr             savePort;
  1425.     extern void            showAboutMeDialog();
  1426.     extern Boolean        gDoneFlag;
  1427.     short                ignore;
  1428.         
  1429.     theItem = LoWord(mResult);
  1430.     theMenu = HiWord(mResult);        /* This is the resource ID */
  1431.  
  1432.     switch (theMenu) {
  1433.         case appleID:
  1434.             if (theItem == aboutMeCommand) 
  1435.                 showAboutMeDialog();
  1436.             else {
  1437.                 GetItem(GetMHandle(appleID), theItem, daName);
  1438.                 GetPort(&savePort);
  1439.                 ignore = OpenDeskAcc(daName);
  1440.                 SetPort(savePort);
  1441.                 }
  1442.             break;
  1443.  
  1444.         case fileID:
  1445.             switch (theItem) {
  1446.                 case lookupCommand:
  1447.                     ShowWindow(gLookupDialog);        /* show lookup prefs window */
  1448.                     SelectWindow(gLookupDialog);
  1449.                     break;
  1450.                 case quitCommand:
  1451.                     gDoneFlag = true;                /* Request exit */
  1452.                     break;
  1453.                 default:
  1454.                     break;
  1455.                 }
  1456.             break;
  1457.  
  1458.         case editID:
  1459.             /*
  1460.              * If this is for a 'standard' edit item,
  1461.              * run it through SystemEdit first.
  1462.              * SystemEdit will return false if it's not a system window.
  1463.              */
  1464.             if ((theItem <= clearCommand) && SystemEdit(theItem-1)) {
  1465.                 break;
  1466.             }
  1467.             
  1468.             /*
  1469.              * Otherwise, it's my window.
  1470.              * and we don't need the Edit menu so boogie...
  1471.              */
  1472.             if(FrontWindow() == gLookupDialog) {
  1473.                 SysBeep(1);
  1474.             }
  1475.             break;        
  1476.         default:
  1477.             break;
  1478.  
  1479.         } /*endsw theMenu*/
  1480.  
  1481.     HiliteMenu(0);
  1482. } /* doCommand */
  1483.  
  1484.  
  1485.  
  1486. /* 
  1487.  *    handles "OK" button outlining for our About...& Echo dialogs.
  1488.  */
  1489. pascal void aboutDialogOKFrame (WindowPtr theWindow, short itemNo)
  1490. {
  1491.     Rect        r;
  1492.     short        kind;
  1493.     Handle        h;
  1494.     PenState    ps;
  1495.  
  1496.     GetPenState(&ps);
  1497.     GetDItem(theWindow, itemNo, &kind, &h, &r);
  1498.     PenSize(3, 3);
  1499.     FrameRoundRect(&r, 16, 16);
  1500.     SetPenState(&ps);
  1501. }
  1502.  
  1503.  
  1504. /* 
  1505.  *    these few lines center the about box to the main screen 1/6 of the way from the bottom of the 
  1506.  *    menubar to the bottom of the main screen.  so decreeth the great John S. 
  1507.  *    noticed the skilled non-use of "with" 
  1508.  */
  1509. void centerDialog(WindowPtr theWindow)
  1510. {
  1511.     short        h, v;
  1512.  
  1513.     #ifdef THINK_C
  1514.         h = (screenBits.bounds.right - screenBits.bounds.left) / 2 - (theWindow->portRect.right - theWindow->portRect.left) / 2;
  1515.         v = (screenBits.bounds.bottom - screenBits.bounds.top) - (theWindow->portRect.bottom - theWindow->portRect.top) - GetMBarHeight();
  1516.     #else
  1517.         h = (qd.screenBits.bounds.right - qd.screenBits.bounds.left) / 2 - (theWindow->portRect.right - theWindow->portRect.left) / 2;
  1518.         v = (qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - (theWindow->portRect.bottom - theWindow->portRect.top) - GetMBarHeight();
  1519.     #endif
  1520.         v = (v / 3) + GetMBarHeight();
  1521.         
  1522.     /* 
  1523.      *    move the window to the right spot & display it & wait around 
  1524.      */
  1525.     MoveWindow(theWindow, h, v, true);
  1526. }
  1527.  
  1528. /*
  1529.  *     Display the About... dialog.
  1530.  *     Then wait until the OK button is clicked before returning.
  1531.  */
  1532. void showAboutMeDialog(void)
  1533. {
  1534.     GrafPtr     savePort;
  1535.     DialogPtr    aboutDialog;
  1536.     short        itemType;
  1537.     Handle        itemHdl;
  1538.     Rect        itemRect;
  1539.     short        itemHit = 0;
  1540.     UserItemUPP    aboutBoxUPP;
  1541.     
  1542.     GetPort(&savePort);
  1543.     aboutDialog = GetNewDialog(aboutMeDLOG, nil, (WindowPtr) -1);
  1544.     
  1545.     /* 
  1546.      *    set up the userItem proc for the "OK" button outline 
  1547.      */
  1548.     GetDItem(aboutDialog, 7, &itemType, &itemHdl, &itemRect);
  1549.     aboutBoxUPP = NewUserItemProc(aboutDialogOKFrame);
  1550.     SetDItem(aboutDialog, 7, userItem, (Handle) aboutBoxUPP, &itemRect);
  1551.  
  1552.     centerDialog((WindowPtr) aboutDialog);
  1553.     
  1554.     ShowWindow(aboutDialog);
  1555.     
  1556. #ifdef THINK_C
  1557.     while(itemHit != OK) 
  1558.         ModalDialog(0L, &itemHit);
  1559. #else
  1560.     while(itemHit != ok) 
  1561.         ModalDialog(0L, &itemHit);
  1562. #endif
  1563.  
  1564.     DisposDialog(aboutDialog);
  1565.  
  1566.     SetPort(savePort);
  1567.  
  1568. #ifdef powerc
  1569.     DisposeRoutineDescriptor(aboutBoxUPP);
  1570. #endif
  1571.  
  1572. } /* showAboutMeDialog */
  1573.  
  1574. void BigBadError(Str255    message)
  1575. {
  1576.     short        itemHit;
  1577.  
  1578.     SetCursor(&qd.arrow);
  1579.     /* type Str255 is an array in MPW 3 */
  1580.     ParamText(message, "\p", "\p", "\p");
  1581.     itemHit = Alert(rUserAlert, nil);
  1582.     closeUpOurAppleTalk();
  1583.     ExitToShell();
  1584. } /* BigBadError */
  1585.  
  1586. /* the following code is from IM VI 3-8 which demonstrates how to check for the 
  1587.  * availability of traps
  1588.  */
  1589.  
  1590. short NumToolboxTraps(void)
  1591. {
  1592.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  1593.         return(0x200);
  1594.     else
  1595.         return(0x400);
  1596.  
  1597. } /* NumToolboxTraps */
  1598.  
  1599. TrapType GetTrapType(short theTrap)
  1600. {
  1601.     short    trapMask = 0x0800;
  1602.     
  1603.     if (theTrap & trapMask)
  1604.         return(ToolTrap);
  1605.     else
  1606.         return(OSTrap);
  1607.  
  1608. } /* GetTrapType */
  1609.  
  1610. Boolean TrapAvailable(short theTrap)
  1611. {
  1612.     TrapType    theType;
  1613.     
  1614.     theType = GetTrapType(theTrap);
  1615.     if (theType == ToolTrap) {
  1616.         theTrap &= 0x07FF;
  1617.         if (theTrap >= NumToolboxTraps())
  1618.             theTrap = _Unimplemented;
  1619.     }
  1620.     return(NGetTrapAddress(theTrap, theType) != NGetTrapAddress(_Unimplemented, ToolTrap));
  1621. }
  1622.  
  1623. /* the following code determines whether VM is active or not
  1624.  * returns false if VM is not on or is not available
  1625.  * returns true if VM is active
  1626.  */
  1627.  
  1628. Boolean IsVMOn(void)
  1629. {
  1630.     long    message;
  1631.     
  1632.     if (!TrapAvailable((short)_Gestalt))
  1633.         return(false);            /* if there is no Gestalt, then VM wont be on */
  1634.         
  1635.     if(Gestalt(gestaltVMAttr, &message))
  1636.         return (false);
  1637.     
  1638.     if (BitTst((Ptr)&message, 31 - gestaltVMPresent))
  1639.         return (true);
  1640.     else
  1641.         return (false);
  1642.     
  1643. } /* IsVMOn */
  1644.